#include <iostream>
#include <unistd.h> //#include <assert.h>//对比于assert.h和stdio.h我们写成cassert和cstdio更好——去掉.h，在头文件前面加上c
#include <cstdio>
#include <cstring>
#include <string>
#include <cassert>
#include <sys/types.h>
#include <sys/wait.h>

using namespace std;
int main() // 父进程读取，子进程写入
{
    // 1、创建管道，打开读写端
    int fds[2];
    int ret = pipe(fds);
    assert(ret == 0);

    // 2、fork子进程
    pid_t id = fork();
    assert(id >= 0);
    const char *s = "我是子进程,我正在给你发消息";
    int cnt = 0;
    if (id == 0) // 子进程
    {
        // 子进程通信代码
        close(fds[0]);
        while (1)
        {
            char buffer[1024];
            ++cnt;
            snprintf(buffer, sizeof(buffer), "child->parent say: %s[%d][%d]", s, cnt, getpid());
            write(fds[1], buffer, strlen(buffer)); // 不考虑\0作为结尾
            // sleep(1);//每隔1s向管道写一次
            // sleep(6);//5s写一次
            cout << "count: " << cnt << endl; // 统计缓冲区的容量
            // sleep(50);
            // break;//写入一行消息，直接退出写端
        }
        close(fds[1]); // 退出写端，关闭文件描述符
        cout << "子进程关闭自己的写端" << endl;
        //sleep(10000);
        exit(-1);
    }
    // 父进程通信代码
    close(fds[1]);
    while (1)
    {
        sleep(2);//写端写一行数据退出，关闭文件描述符。读端等待两秒，读取到0就退出
        char buffer[1024];
        // cout << "AAAAAAAAAAAAAAAAAAAAAA" << endl;
        // 如果管道中没有了数据，读端在读，默认会直接阻塞当前正在读取的进程！
        ssize_t n = read(fds[0], buffer, sizeof(buffer) - 1); // 写入速度慢，读取会卡在read这里，等待写端继续写入
        // cout << "BBBBBBBBBBBBBBBBBBBBBB" << endl;
        if (n > 0)
        {
            buffer[n] = 0;
            cout << "Get Message# " << buffer << " | my pid: " << getpid() << endl;
        }
        else if (n == 0)//写端关闭
        {
            // 读到文件结尾
            cout << "read: " << s << endl;
            break;
        }
        //else
        //{
            break;//写端一直写，读端关闭
        //}
    }
    close(fds[0]);//提前关闭文件描述符
    cout << "父进程关闭读端" << endl;
    int status = 0;
    ret = waitpid(id, &status, 0);
    assert(ret == id);
    cout <<"pid->"<< ret << " : "<< (status & 0x7F) << endl;

    // ret = waitpid(id, nullptr, 0);
    // assert(ret == id);
    // close(fds[0]);
    // 0，1，2是输入输出错误流，那pipe的结果哪一个是读，哪一个是写呢？
    // [0]: 读取，嘴巴，读书的
    // [1]: 写入，钢笔，写的
    // cout << "fds[0]" << fds[0] << endl;
    // cout << "fds[1]" << fds[1] << endl;
    return 0;
}
